// Test for BAlloc

#include <gtest/gtest.h>
#include "balloc.h"


const int HEAP_SIZE = 16 * 1024;

class BallocTest : public testing::Test {
protected:
	virtual void SetUp() {
		balloc_init(&balc, buf, sizeof(buf));
	}

	virtual void TearDown() {
	}

	unsigned long buf[HEAP_SIZE / sizeof(unsigned long)];
	BAlloc balc;
};


//=============================================================================

TEST_F(BallocTest, Allocate) {
	void* p = balloc(&balc, 1234);
	EXPECT_TRUE(p != NULL) << "Can allocate";
	// no need to bfree
}

TEST_F(BallocTest, CantAllocate) {
	void* p = balloc(&balc, HEAP_SIZE);
	EXPECT_TRUE(p == NULL) << "Can't allocate";
}

TEST_F(BallocTest, FreeNullPointer) {
	bfree(&balc, NULL); // "Can free null pointer";
}

TEST_F(BallocTest, AllocateWithSizeZero) {
	void* p = balloc(&balc, 0);
	EXPECT_TRUE(p != NULL) << "Can allocate 0 byte";
}

TEST_F(BallocTest, AllocateMax) {
	int total_free_size, max_block_size;
	balloc_get_info(&balc, &total_free_size, &max_block_size);
	void* p = balloc(&balc, max_block_size);
	EXPECT_TRUE(p != NULL) << "Can allocate max size: " << max_block_size;
}

TEST_F(BallocTest, AllocateRandom) {
	const int TEST_NUM = 2048;
	const int N = 16;
	const int ALLOC_MAX_SIZE = 64;
	void* work[N];
	memset(work, 0x00, sizeof(work));
	for (int i=0; i<TEST_NUM; ++i) {
		int slot = rand() * N / (RAND_MAX + 1);
		if (work[slot] == NULL) {
			int size = rand() * ALLOC_MAX_SIZE / RAND_MAX;
			void* p = balloc(&balc, size);
			EXPECT_TRUE(p != NULL);
			work[slot] = p;
		} else {
			bfree(&balc, work[slot]);
			work[slot] = NULL;
		}
	}
}
